home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1998 April: Mac OS SDK / Dev.CD Apr 98 SDK1.toast / Development Kits (Disc 1) / QuickDraw 3D / Samples / SampleCode / Picking Mesh ShapeParts / Sources / PickMeshShapePart.c next >
Encoding:
Text File  |  1997-08-14  |  16.3 KB  |  672 lines  |  [TEXT/CWIE]

  1. // PickMeshShapePart.c
  2. //
  3. // This demonstrates how to use picks  to test which parts of a mesh geometry have
  4. // been hit.  When the mesh is picked the fPickParts value set from the ShapeParts
  5. // menu controls the parts tested: object, face, edge, or vertex.  As the returned
  6. // hits  in the pick are processed the corresponding part of the mesh is draw in a
  7. // different color  and the name  of that part is displayed in the window's  upper
  8. // left corner.
  9. //
  10. // The vertex and edge tolerance levels  set in CreatePick() control how close the
  11. // window point pick must be to the given part.
  12. //
  13. // Robert Dierkes - November 11, 1995
  14. // 
  15. // ©1994-95 Apple computer Inc., All Rights Reserved
  16. //
  17.  
  18. // system headers
  19. #include <Windows.h>
  20.  
  21. // for QuickDraw 3D
  22. #include "QD3D.h"
  23. #include "QD3DMath.h"
  24. #include "QD3DDrawContext.h"
  25. #include "QD3DShader.h"
  26. #include "QD3DGroup.h"
  27. #include "QD3DPick.h"
  28.  
  29.  
  30. #include "PickMeshShapePart.h"
  31.  
  32.  
  33. //-------------------------------------------------------------------------------------------
  34. // function prototypes
  35.  
  36. void TickDelay(
  37.     long    time);
  38.  
  39. TQ3Status DoGroupPicking(
  40.     TQ3ViewObject        view,
  41.     TQ3GroupObject        group,
  42.     TQ3PickObject        pick);
  43.  
  44. void GetRandomRGBColor(
  45.     TQ3ColorRGB        *pColorRGB);
  46.  
  47. TQ3Status ChangeMeshFaceColor(
  48.     TQ3GeometryObject    meshGeo,
  49.     TQ3MeshFace            meshFace,
  50.     DocumentPtr            theDocument);
  51.  
  52. TQ3Status ChangeMeshEdgeColor(
  53.     TQ3GeometryObject    meshGeo,
  54.     TQ3MeshEdge            meshEdge,
  55.     DocumentPtr            theDocument);
  56.  
  57. TQ3Status ChangeMeshVertexColor(
  58.     TQ3GeometryObject    meshGeo,
  59.     TQ3MeshVertex        meshVertex,
  60.     DocumentPtr            theDocument);
  61.  
  62. TQ3Status HandleMeshShapePart(
  63.     TQ3GeometryObject    geometry,
  64.     TQ3ShapePartObject    shapePart,
  65.     DocumentPtr            theDocument);
  66.  
  67. TQ3Status HandleMeshPickHits(
  68.     TQ3PickObject        pick,
  69.     DocumentPtr            theDocument);
  70.  
  71. TQ3Status CreatePick(
  72.     TQ3PickObject        *pPick);
  73.  
  74.  
  75. //-------------------------------------------------------------------------------------------
  76. //
  77.  
  78. #define    kDelay            30
  79. #define    kTextLocationX    30
  80. #define    kTextLocationY    30
  81.  
  82. static TQ3PickObject    gPick = NULL;
  83.  
  84.  
  85.  
  86. //-----------------------------------------------------------------------------
  87. // 
  88. //  InitPicking
  89.  
  90.  
  91. TQ3Status InitPicking(
  92.     void)
  93. {
  94.     return CreatePick(&gPick);
  95. }
  96.  
  97.  
  98. //-----------------------------------------------------------------------------
  99. // 
  100. //  ExitPicking
  101.  
  102. TQ3Status ExitPicking(
  103.     void)
  104. {
  105.     if (gPick != NULL) {
  106.         Q3Object_Dispose(gPick);
  107.         gPick = NULL;
  108.     }
  109.  
  110.     return kQ3Success;
  111. }
  112.  
  113.  
  114. //-----------------------------------------------------------------------------
  115. // 
  116. //  TickDelay
  117.  
  118. static
  119. void TickDelay(
  120.     long    time)
  121. {
  122.     long    ticks,
  123.             startTicks;
  124.  
  125.     startTicks = ticks = TickCount();
  126.  
  127.     while (ticks - startTicks != time ) {
  128.         ticks = TickCount();
  129.     }
  130. }
  131.  
  132.  
  133. //-----------------------------------------------------------------------------
  134. // 
  135. //  DoGroupPicking
  136.  
  137. static
  138. TQ3Status DoGroupPicking(
  139.     TQ3ViewObject        view,
  140.     TQ3GroupObject        group,
  141.     TQ3PickObject        pick)
  142. {
  143.     TQ3Status            status;
  144.     TQ3ViewStatus        viewStatus;
  145.  
  146.     if ((status = Q3View_StartPicking(view, pick)) == kQ3Failure)
  147.         return status;
  148.  
  149.     do {
  150.         status = Q3DisplayGroup_Submit(group, view);
  151.  
  152.         viewStatus = Q3View_EndPicking(view);
  153.     } while (viewStatus == kQ3ViewStatusRetraverse);
  154.  
  155.     if (viewStatus != kQ3ViewStatusDone) {
  156.         status = kQ3Failure;
  157.     }
  158.  
  159.     return status;
  160. }
  161.  
  162.  
  163. //-----------------------------------------------------------------------------
  164. // 
  165. //  GetRandomRGBColor
  166.  
  167. static
  168. void GetRandomRGBColor(
  169.     TQ3ColorRGB        *pColorRGB)
  170. {
  171.     unsigned long    ticks;
  172.  
  173.     ticks = TickCount();
  174.     Q3ColorRGB_Set(pColorRGB,
  175.         (ticks % 10)   / 10.0,
  176.         (ticks % 100)  / 100.0,
  177.         (ticks % 1000) / 1000.0);
  178. }
  179.  
  180.  
  181. //-----------------------------------------------------------------------------
  182. // 
  183. //  ChangeMeshFaceColor
  184.  
  185. static
  186. TQ3Status ChangeMeshFaceColor(
  187.     TQ3GeometryObject    meshGeo,
  188.     TQ3MeshFace            meshFace,
  189.     DocumentPtr            theDocument)
  190. {
  191.     TQ3Status        status;
  192.     TQ3AttributeSet    attributeSet;
  193.     TQ3ColorRGB        colorRGB;
  194.  
  195.     status = kQ3Failure;
  196.  
  197.     if (meshGeo  == NULL  ||
  198.         meshFace == NULL) {
  199.         return status;
  200.     }
  201.  
  202.     /* Get the face attributes */
  203.     if ((status = Q3Mesh_GetFaceAttributeSet(meshGeo, meshFace, &attributeSet)) == kQ3Failure) {
  204.         return status;
  205.     }
  206.  
  207.     /* Create an attributes if none */
  208.     if (attributeSet == NULL) {
  209.         if ((attributeSet = Q3AttributeSet_New()) == NULL) {
  210.             return kQ3Failure;
  211.         }
  212.     }
  213.  
  214.     GetRandomRGBColor(&colorRGB);
  215.     if ((status = Q3AttributeSet_Add(attributeSet, kQ3AttributeTypeDiffuseColor, &colorRGB)) == kQ3Success) {
  216.  
  217.         char    partTypeString[] = {"\pFace"};
  218.  
  219.         /* Set new face color */
  220.         status = Q3Mesh_SetFaceAttributeSet(meshGeo, meshFace, attributeSet);
  221.  
  222.         /* Redraw the mesh */
  223.         DrawDocumentData(theDocument);
  224.         MoveTo(kTextLocationX, kTextLocationY);
  225.         DrawText((void *) partTypeString, 1, (short) partTypeString[0]);
  226.         TickDelay(kDelay);
  227.  
  228.         /* Remove new face color */
  229.         status = Q3Mesh_SetFaceAttributeSet(meshGeo, meshFace, NULL);
  230.         DrawDocumentData(theDocument);
  231.     }
  232.  
  233.     Q3Object_Dispose(attributeSet);
  234.  
  235.     return status;
  236. }
  237.  
  238.  
  239. //-----------------------------------------------------------------------------
  240. // 
  241. //  ChangeMeshEdgeColor
  242.  
  243. static
  244. TQ3Status ChangeMeshEdgeColor(
  245.     TQ3GeometryObject    meshGeo,
  246.     TQ3MeshEdge            meshEdge,
  247.     DocumentPtr            theDocument)
  248. {
  249.     TQ3Status        status;
  250.     TQ3AttributeSet    attributeSet1,
  251.                     attributeSet2;
  252.     TQ3MeshVertex    meshVertex1,
  253.                     meshVertex2;
  254.     TQ3ColorRGB        colorRGB;
  255.  
  256.     status = kQ3Failure;
  257.  
  258.     if ((meshGeo  == NULL)  ||
  259.         (meshEdge == NULL)  ||
  260.         (theDocument == NULL)) {
  261.         debugstr("ChangeMeshEdgeColor: NULL parameter passed");
  262.         return status;
  263.     }
  264.  
  265.     attributeSet1 = NULL;
  266.     attributeSet2 = NULL;
  267.  
  268.     /*
  269.      * Set color on both vertices of this edge
  270.      *
  271.      * We change the vertex attributes instead of the edge attributes because we can only
  272.      * see the effects of an edge attribute when the fill style is kQ3FillStyleEdges.  We
  273.      * could use kQ3FillStyleEdges rather than the current fill of kQ3FillStyleFilled but
  274.      * then we couldn't see the attributes on the vertex and face. 
  275.      */
  276.     if ((status = Q3Mesh_GetEdgeVertices(meshGeo, meshEdge, &meshVertex1, &meshVertex2)) == kQ3Failure) {
  277.         return status;
  278.     }
  279.  
  280.     /* Get the vertex attributes */
  281.     if (((status = Q3Mesh_GetVertexAttributeSet(meshGeo, meshVertex1, &attributeSet1)) == kQ3Failure)  ||
  282.         ((status = Q3Mesh_GetVertexAttributeSet(meshGeo, meshVertex2, &attributeSet2)) == kQ3Failure)) {
  283.         goto ChangeMeshEdgeColor_Exit;
  284.     }
  285.  
  286.     /* Create an attributes if none */
  287.     if (attributeSet1 == NULL) {
  288.         if ((attributeSet1 = Q3AttributeSet_New()) == NULL) {
  289.             goto ChangeMeshEdgeColor_Exit;
  290.         }
  291.     }
  292.  
  293.     if (attributeSet2 == NULL) {
  294.         if ((attributeSet2 = Q3AttributeSet_New()) == NULL) {
  295.             goto ChangeMeshEdgeColor_Exit;
  296.         }
  297.     }
  298.  
  299.     GetRandomRGBColor(&colorRGB);
  300.     if (((status = Q3AttributeSet_Add(attributeSet1, kQ3AttributeTypeDiffuseColor, &colorRGB)) == kQ3Success)  &&
  301.         ((status = Q3AttributeSet_Add(attributeSet2, kQ3AttributeTypeDiffuseColor, &colorRGB)) == kQ3Success)) {
  302.  
  303.         char    partTypeString[] = {"\pEdge"};
  304.  
  305.         /* Set new vertex color */
  306.         if (((status = Q3Mesh_SetVertexAttributeSet(meshGeo, meshVertex1, attributeSet1)) == kQ3Success)  &&
  307.             ((status = Q3Mesh_SetVertexAttributeSet(meshGeo, meshVertex2, attributeSet2)) == kQ3Success)) {
  308.  
  309.             /* Redraw the mesh */
  310.             DrawDocumentData(theDocument);
  311.             MoveTo(kTextLocationX, kTextLocationY);
  312.             DrawText((void *) partTypeString, 1, (short) partTypeString[0]);
  313.             TickDelay(kDelay);
  314.         }
  315.  
  316.         /* Remove new vertex color */
  317.         status = Q3Mesh_SetVertexAttributeSet(meshGeo, meshVertex1, NULL);
  318.         status = Q3Mesh_SetVertexAttributeSet(meshGeo, meshVertex2, NULL);
  319.         DrawDocumentData(theDocument);
  320.     }
  321.  
  322. ChangeMeshEdgeColor_Exit:
  323.  
  324.     if (attributeSet1 != NULL)
  325.         Q3Object_Dispose(attributeSet1);
  326.  
  327.     if (attributeSet2 != NULL)
  328.         Q3Object_Dispose(attributeSet2);
  329.  
  330.     return status;
  331. }
  332.  
  333.  
  334. //-----------------------------------------------------------------------------
  335. // 
  336. //  ChangeMeshVertexColor
  337.  
  338. static
  339. TQ3Status ChangeMeshVertexColor(
  340.     TQ3GeometryObject    meshGeo,
  341.     TQ3MeshVertex        meshVertex,
  342.     DocumentPtr            theDocument)
  343. {
  344.     TQ3Status        status;
  345.     TQ3AttributeSet    attributeSet;
  346.     TQ3ColorRGB        colorRGB;
  347.  
  348.     status = kQ3Failure;
  349.  
  350.     if ((meshGeo  == NULL)  ||
  351.         (meshVertex == NULL)  ||
  352.         (theDocument == NULL)) {
  353.         debugstr("ChangeMeshVertexColor: NULL parameter passed");
  354.         return status;
  355.     }
  356.  
  357.     /* Get the vertex attributes */
  358.     if ((status = Q3Mesh_GetVertexAttributeSet(meshGeo, meshVertex, &attributeSet)) == kQ3Failure) {
  359.         return status;
  360.     }
  361.  
  362.     /* Create an attributes if none */
  363.     if (attributeSet == NULL) {
  364.         if ((attributeSet = Q3AttributeSet_New()) == NULL) {
  365.             return kQ3Failure;
  366.         }
  367.     }
  368.  
  369.     GetRandomRGBColor(&colorRGB);
  370.     if ((status = Q3AttributeSet_Add(attributeSet, kQ3AttributeTypeDiffuseColor, &colorRGB)) == kQ3Success) {
  371.  
  372.         char    partTypeString[] = {"\pVertex"};
  373.  
  374.         /* Set new vertex color */
  375.         status = Q3Mesh_SetVertexAttributeSet(meshGeo, meshVertex, attributeSet);
  376.  
  377.         /* Redraw the mesh */
  378.         DrawDocumentData(theDocument);
  379.         MoveTo(kTextLocationX, kTextLocationY);
  380.         DrawText((void *) partTypeString, 1, (short) partTypeString[0]);
  381.         TickDelay(kDelay);
  382.  
  383.         /* Remove new vertex color */
  384.         status = Q3Mesh_SetVertexAttributeSet(meshGeo, meshVertex, NULL);
  385.         DrawDocumentData(theDocument);
  386.     }
  387.  
  388.     Q3Object_Dispose(attributeSet);
  389.  
  390.     return status;
  391. }
  392.  
  393.  
  394. //-----------------------------------------------------------------------------
  395. // 
  396. //  HandleMeshShapePart
  397.  
  398. static
  399. TQ3Status HandleMeshShapePart(
  400.     TQ3GeometryObject    geometry,
  401.     TQ3ShapePartObject    shapePart,
  402.     DocumentPtr            theDocument)
  403. {
  404.     TQ3Status            status;
  405.     TQ3ObjectType        objectType;
  406.  
  407.     if ((geometry == NULL)  || (shapePart == NULL)  ||  (theDocument == NULL)) {
  408.         debugstr("HandleMeshShapePart: NULL parameter passed");
  409.         return kQ3Failure;
  410.     }
  411.  
  412.     /* Is object a mesh geometry? */
  413.     if (Q3Object_IsType (geometry, kQ3GeometryTypeMesh) == kQ3False) {
  414.         debugstr("HandleMeshShapePart: geometry isn't a mesh");
  415.         return kQ3Failure;
  416.     }
  417.  
  418.     /* Is the shapePart a mesh part? */
  419.     if (Q3ShapePart_GetType (shapePart) != kQ3ShapePartTypeMeshPart) {
  420.         debugstr("HandleMeshShapePart: shape part isn't for a mesh");
  421.         return kQ3Failure;
  422.     }
  423.  
  424.     status = kQ3Failure;
  425.  
  426.     /* Or use this to get the shape part hit: objectType = Q3Object_GetLeafType(shapePart); */
  427.     objectType = Q3MeshPart_GetType(shapePart);
  428.  
  429.     switch (objectType) {
  430.         case kQ3MeshPartTypeMeshFacePart:
  431.             {
  432.                 TQ3MeshFace        meshFace;
  433.  
  434.                 if (Q3MeshFacePart_GetFace(shapePart, &meshFace) == kQ3Success) {
  435.                     status = ChangeMeshFaceColor(geometry, meshFace, theDocument);
  436.                 }
  437.             }
  438.             break;
  439.  
  440.         case kQ3MeshPartTypeMeshEdgePart:
  441.             {
  442.                 TQ3MeshEdge        meshEdge;
  443.  
  444.                 if (Q3MeshEdgePart_GetEdge(shapePart, &meshEdge) == kQ3Success) {
  445.                     status = ChangeMeshEdgeColor(geometry, meshEdge, theDocument);
  446.                 }
  447.             }
  448.             break;
  449.  
  450.         case kQ3MeshPartTypeMeshVertexPart:
  451.             {
  452.                 TQ3MeshVertex    meshVertex;
  453.  
  454.                 if (Q3MeshVertexPart_GetVertex(shapePart, &meshVertex) == kQ3Success) {
  455.                     status = ChangeMeshVertexColor(geometry, meshVertex, theDocument);
  456.                 }
  457.             }
  458.             break;
  459.  
  460.         default:
  461.             status = kQ3Failure;
  462.             break;
  463.     }
  464.  
  465.     return status;
  466. }
  467.  
  468.  
  469. //-----------------------------------------------------------------------------
  470. // 
  471. //  HandleMeshPickHits
  472.  
  473. static
  474. TQ3Status HandleMeshPickHits(
  475.     TQ3PickObject        pick,
  476.     DocumentPtr            theDocument)
  477. {
  478.     TQ3Status            status;
  479.     unsigned long        hitIndex,
  480.                         numHits;
  481. #if defined(QD3D_OBSOLETE) && QD3D_OBSOLETE
  482.     TQ3HitData            hitData;
  483. #else  /* ! QD3D_OBSOLETE */
  484.     TQ3PickDetail        validMask;
  485.     TQ3Object            object;
  486.     TQ3ShapePartObject    shapePart;
  487.  
  488.     object    = NULL;
  489.     shapePart = NULL;
  490. #endif /* ! QD3D_OBSOLETE */
  491.  
  492.  
  493.     if ((pick == NULL)  ||  (theDocument == NULL)) {
  494.         debugstr("HandleMeshPickHits: NULL parameter passed");
  495.         return kQ3Failure;
  496.     }
  497.  
  498.     numHits = 0;
  499.     if (Q3Pick_GetNumHits(pick, &numHits) == kQ3Failure) {
  500.         debugstr("HandleMeshPickHits: NULL parameter passed");
  501.         return kQ3Failure;
  502.     }
  503.  
  504.     /* Process each hit in the pick */
  505.     for (hitIndex = 0, status = kQ3Success;
  506.         (hitIndex < numHits) && (status == kQ3Success);
  507.          hitIndex++) {
  508.  
  509. #if defined(QD3D_OBSOLETE) && QD3D_OBSOLETE
  510.  
  511.         if (Q3Pick_GetHitData(pick, hitIndex, &hitData) == kQ3Failure) {
  512.             debugstr("HandleMeshPickHits: Q3Pick_GetHitData failed");
  513.             status = kQ3Failure;
  514.             goto HandleMeshPickHits_Cleanup;
  515.         }
  516.  
  517.         /* Test if hit data contains an object and shape part */
  518.  
  519.         /* Get reference to geometry object hit */
  520.         if (! HitData_Has_Object(hitData)) {
  521.             debugstr("HandleMeshPickHits: no object information returned in Q3Pick_GetHitData");
  522.             status = kQ3Failure;
  523.             goto HandleMeshPickHits_Cleanup;
  524.         }
  525.  
  526.         /* Get reference to shapePart hit */
  527.         if (! HitData_Has_ShapePart(hitData)) {
  528.             debugstr("HandleMeshPickHits: no shape part information returned in Q3Pick_GetHitData");
  529.             status = kQ3Failure;
  530.             goto HandleMeshPickHits_Cleanup;
  531.         }
  532.  
  533.         /* Color the shape part(s) hit */
  534.         (void) HandleMeshShapePart(hitData.object, hitData.shapePart, theDocument);
  535.  
  536.         /* Dispose hitData.object and hitData.shapePart returned with Q3Pick_GetHitData */
  537. HandleMeshPickHits_Cleanup:
  538.         Q3Hit_EmptyData(&hitData);
  539.  
  540. #else    /* ! QD3D_OBSOLETE */
  541.         
  542.         /*
  543.          * New Picking API for QuickDraw 3D Release 1.5
  544.          */
  545.  
  546.         /* Get the TQ3PickDetail masks for this hit  (hitIndex) */
  547.         if ((status = Q3Pick_GetPickDetailValidMask(pick, hitIndex, &validMask)) == kQ3Failure) {
  548.             debugstr("HandleMeshPickHits: Q3Pick_GetPickDetailValidMask failed");
  549.             goto HandleMeshPickHits_Cleanup;
  550.         }
  551.  
  552.         /* Quick check to see if the hit contains an object and shape part */
  553.         if (! (validMask & kQ3PickDetailMaskObject)  ||
  554.             ! (validMask & kQ3PickDetailMaskShapePart) ) {
  555.             debugstr("HandleMeshPickHits: expected object and shapePart TQ3PickDetailMasks masks to be set");
  556.             status = kQ3Failure;
  557.             goto HandleMeshPickHits_Cleanup;
  558.         }
  559.  
  560.         /* Get reference to geometry object hit */
  561.         if ((status = Q3Pick_GetPickDetailData(pick, hitIndex, kQ3PickDetailMaskObject, &object)) == kQ3Failure) {
  562.             debugstr("HandleMeshPickHits: no object returned in Q3Pick_GetPickDetailData");
  563.             goto HandleMeshPickHits_Cleanup;
  564.         }
  565.  
  566.         /* Get reference to shapePart hit */
  567.         if ((status = Q3Pick_GetPickDetailData(pick, hitIndex, kQ3PickDetailMaskShapePart, &shapePart)) == kQ3Failure) {
  568.             debugstr("HandleMeshPickHits: no object returned in Q3Pick_GetPickDetailData");
  569.             goto HandleMeshPickHits_Cleanup;
  570.         }
  571.  
  572.         /* Color the shape part(s) hit */
  573.         (void) HandleMeshShapePart(object, shapePart, theDocument);
  574.  
  575.         /* Dispose object and shapePart returned with Q3Pick_GetPickDetailData */
  576. HandleMeshPickHits_Cleanup:
  577.         if (object != NULL) {
  578.             Q3Object_Dispose(object);
  579.             object = NULL;
  580.         }
  581.         if (shapePart != NULL) {
  582.             Q3Object_Dispose(shapePart);
  583.             shapePart = NULL;
  584.         }
  585.  
  586. #endif /* ! QD3D_OBSOLETE */
  587.     }
  588.  
  589.  
  590.     /*
  591.      * If we reuse the pick object be sure to empty the hit list.
  592.      * If the pick object is disposed immediately after picking
  593.      * (not the case in this sample code) the hit list is automatically disposed.
  594.      */
  595.     if (Q3Pick_EmptyHitList(pick) == kQ3Failure) {
  596.         debugstr("HandleMeshPickHits: Q3Pick_EmptyHitList failed");
  597.     }
  598.  
  599.     return status;
  600. }
  601.  
  602.  
  603. //-----------------------------------------------------------------------------
  604. // 
  605. //  CreatePick
  606.  
  607. static
  608. TQ3Status CreatePick(
  609.     TQ3PickObject        *pPick)
  610. {
  611.     TQ3WindowPointPickData    data;
  612.     TQ3Status                status;
  613.  
  614.     status = kQ3Failure;
  615.  
  616.     if (pPick  == NULL)
  617.         return status;
  618.  
  619.     /* Create pick object */
  620.     data.data.sort = kQ3PickSortNearToFar;
  621.     data.data.mask = kQ3PickDetailMaskObject  |    /* Request only object and shape parts */
  622.                      kQ3PickDetailMaskShapePart;
  623.     data.data.numHitsToReturn = kQ3ReturnAllHits;
  624.     
  625.     Q3Point2D_Set(&data.point, 0.0, 0.0);
  626.     data.vertexTolerance = 5.0;                    /* Set vertex and edge tolerences */
  627.     data.edgeTolerance   = 3.0;
  628.  
  629.     if ((*pPick = Q3WindowPointPick_New(&data)) != NULL)
  630.         status = kQ3Success;
  631.  
  632.     return status;
  633. }
  634.  
  635.  
  636. //-----------------------------------------------------------------------------
  637. // 
  638. //  DoPicking
  639.  
  640. TQ3Status DoPicking(
  641.     Point                *pWhere,    /* local window coordinates */
  642.     DocumentPtr            theDocument)
  643. {
  644.     TQ3Status            status;
  645.     TQ3Point2D            point;
  646.  
  647.     status = kQ3Failure;
  648.  
  649.     if (theDocument->fView  == NULL  ||
  650.         theDocument->fModel == NULL  ||
  651.         theDocument->fPickPartStyle == NULL  ||
  652.         gPick == NULL) {
  653.  
  654.         return kQ3Failure;
  655.     }
  656.  
  657.     /* Set pick part style with parts selected in the menu */
  658.     if ((status = Q3PickPartsStyle_Set(theDocument->fPickPartStyle, theDocument->fPickParts)) == kQ3Failure)
  659.         return kQ3Failure;
  660.  
  661.     /* Set the pick's point to mouse location */
  662.     Q3Point2D_Set(&point, pWhere->h, pWhere->v);
  663.     if ((status = Q3WindowPointPick_SetPoint(gPick, &point)) == kQ3Failure)
  664.         return kQ3Failure;
  665.  
  666.     if ((status = DoGroupPicking(theDocument->fView, theDocument->fModel, gPick)) == kQ3Failure)
  667.         return kQ3Failure;
  668.  
  669.     /* Handle hit(s) on mesh */
  670.     return HandleMeshPickHits(gPick, theDocument);
  671. }
  672.